package com.baosight.xcyber.tm.re.domain;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.zeroc.Ice.Identity;
import com.zeroc.IceGrid.PropertySetDescriptor;
import com.zeroc.IceGrid.TemplateDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class UITreeNode {
    public static Logger logger = LoggerFactory.getLogger(UITreeNode.class);
    protected static String regex = "\\$\\{[a-zA-Z0-9\\u4E00-\\u9FA5.-]+\\}";
    String type = null;
    String status = null;
    String name = null;
    JSONObject param = new JSONObject();
    List<UITreeNode> children = new ArrayList<>();
    Map<String, TemplateDescriptor> serverTemplates;
    Map<String, TemplateDescriptor> serviceTemplates;

    public String getType() {
        return this.type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getStatus() {
        return this.status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public JSONObject getParam() {
        return this.param;
    }

    public void setParam(JSONObject param) {
        this.param = param;
    }

    public List<UITreeNode> getChildren() {
        return children;
    }

    public void setChildren(List<UITreeNode> children) {
        this.children = children;
    }

    @JsonIgnore
    public Map<String, TemplateDescriptor> getServerTemplates() {
        return serverTemplates;
    }

    protected void setServerTemplates(Map<String, TemplateDescriptor> serverTemplates) {
        this.serverTemplates = serverTemplates;
    }

    protected Map<String, TemplateDescriptor> getServiceTemplates() {
        return serviceTemplates;
    }

    public void setServiceTemplates(Map<String, TemplateDescriptor> serviceTemplates) {
        this.serviceTemplates = serviceTemplates;
    }

    /**
     * 使用${xx} 匹配并替代成application.properties中的配置项
     * exp. xcyber.identity=TreeManager,xCyber/${xcyber.identity} ==>xCyber/TreeManager
     *
     * @param serviceId
     * @param paramVal
     * @return
     */
    protected static String analyzeStr(String serviceId, Map<String, String> paramVal) {

        StringBuffer sb = new StringBuffer();
        Matcher matcher = Pattern.compile(regex).matcher(serviceId);
        while (matcher.find()) {
            String matcherKey = matcher.group();
            String value = matcherKey.substring(2, matcherKey.length() - 1);
            String rVal = paramVal.get(value);
            if(rVal!=null&&rVal.contains("$")){
                rVal=analyzeStr(rVal,paramVal);
            }
            matcher.appendReplacement(sb, rVal == null ? "" : rVal);
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    protected static void replaceObject(Object obj, Map<String, String> paramVal) {
        Field[] fields = obj.getClass().getFields();

        for (int i = 0; i < fields.length; i++) {
            try {
                Field field = fields[i];
                String fileName = field.getName();
                Class<?> type = field.getType();
                if (String.class.isAssignableFrom(type)) {
                    //System.out.printf("String %s %s \n",fileName,type);
                    field.setAccessible(true);
                    String temp = (String) field.get(obj);
                    String val = analyzeStr(temp, paramVal);
                    field.set(obj, val);
                } else if (Iterable.class.isAssignableFrom(type)) {
                    //System.out.printf("Itertable %s %s \n",fileName,type);
                    field.setAccessible(true);
                    Iterable iterator = (Iterable) field.get(obj);
                    iterator.forEach(item -> replaceObject(item, paramVal));
                }else if(Identity.class.isAssignableFrom(type)){
                    field.setAccessible(true);
                    Identity identity= (Identity) field.get(obj);
                    identity.name=analyzeStr(identity.name, paramVal);
                    identity.category=analyzeStr(identity.category, paramVal);
                }else if(PropertySetDescriptor.class.isAssignableFrom(type)){
                    field.setAccessible(true);
                    PropertySetDescriptor propertySetDescriptor= (PropertySetDescriptor) field.get(obj);
                    propertySetDescriptor.properties.forEach(
                            item->replaceObject(item,paramVal));
                }else{
                    //System.out.printf("else %s %s \n",fileName,type);
                }
            } catch (IllegalAccessException e) {
                logger.error(e.getMessage(), e);
            }
        }
    }
}